{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1: Create a Numpy array (from a list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "lst1=[1,2,3]\n",
    "array1 = np.array(lst1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(array1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(lst1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2: Add two Numpy arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 1, 2, 3]\n",
      "[2 4 6]\n"
     ]
    }
   ],
   "source": [
    "lst2 = lst1 + lst1\n",
    "print(lst2)\n",
    "array2 = array1 + array1\n",
    "print(array2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3: Mathematical operations on Numpy arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "array1 multiplied by array1:  [1 4 9]\n",
      "array1 divided by array1:  [1. 1. 1.]\n",
      "array1 raised to the power of array1:  [ 1  4 27]\n"
     ]
    }
   ],
   "source": [
    "print(\"array1 multiplied by array1: \",array1*array1)\n",
    "print(\"array1 divided by array1: \",array1/array1)\n",
    "print(\"array1 raised to the power of array1: \",array1**array1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4: More advanced mathematical operations on Numpy arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5]\n",
      "Sine:  [ 0.84147098  0.90929743  0.14112001 -0.7568025  -0.95892427]\n",
      "Natural logarithm:  [0.         0.69314718 1.09861229 1.38629436 1.60943791]\n",
      "Base-10 logarithm:  [0.         0.30103    0.47712125 0.60205999 0.69897   ]\n",
      "Base-2 logarithm:  [0.         1.         1.5849625  2.         2.32192809]\n",
      "Exponential:  [  2.71828183   7.3890561   20.08553692  54.59815003 148.4131591 ]\n"
     ]
    }
   ],
   "source": [
    "lst_5=[i for i in range(1,6)]\n",
    "print(lst_5)\n",
    "array_5=np.array(lst_5)\n",
    "# sine function\n",
    "print(\"Sine: \",np.sin(array_5))\n",
    "# logarithm\n",
    "print(\"Natural logarithm: \",np.log(array_5))\n",
    "print(\"Base-10 logarithm: \",np.log10(array_5))\n",
    "print(\"Base-2 logarithm: \",np.log2(array_5))\n",
    "# Exponential\n",
    "print(\"Exponential: \",np.exp(array_5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5: How to generate arrays easily? `arange` and `linspace`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A series of numbers: [ 5  6  7  8  9 10 11 12 13 14 15]\n",
      "Numbers spaced apart by 2: [ 0  2  4  6  8 10]\n",
      "Numbers spaced apart by float: [ 0.   2.5  5.   7.5 10. ]\n",
      "Every 5th number from 30 in reverse order:  [30 25 20 15 10  5  0]\n",
      "11 linearly spaced numbers between 1 and 5:  [1.  1.4 1.8 2.2 2.6 3.  3.4 3.8 4.2 4.6 5. ]\n"
     ]
    }
   ],
   "source": [
    "print(\"A series of numbers:\",np.arange(5,16))\n",
    "print(\"Numbers spaced apart by 2:\",np.arange(0,11,2))\n",
    "print(\"Numbers spaced apart by float:\",np.arange(0,11,2.5))\n",
    "print(\"Every 5th number from 30 in reverse order: \",np.arange(30,-1,-5))\n",
    "print(\"11 linearly spaced numbers between 1 and 5: \",np.linspace(1,5,11))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 6: Creating multi-dimensional array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type/Class of this object: <class 'numpy.ndarray'>\n",
      "Here is the matrix\n",
      "----------\n",
      " [[1 2 3]\n",
      " [4 5 6]\n",
      " [7 8 9]] \n",
      "----------\n"
     ]
    }
   ],
   "source": [
    "list_2D = [[1,2,3],[4,5,6],[7,8,9]]\n",
    "mat1 = np.array(list_2D)\n",
    "print(\"Type/Class of this object:\",type(mat1))\n",
    "print(\"Here is the matrix\\n----------\\n\",mat1,\"\\n----------\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1.5 2.  3. ]\n",
      " [4.  5.  6. ]]\n"
     ]
    }
   ],
   "source": [
    "tuple_2D = np.array([(1.5,2,3), (4,5,6)])\n",
    "mat_tuple = np.array(tuple_2D)\n",
    "print (mat_tuple)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 7: Dimension, shape, size, and data type of the 2D array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dimension of this matrix: 2\n",
      "Size of this matrix: 9\n",
      "Shape of this matrix: (3, 3)\n",
      "Data type of this matrix: int32\n"
     ]
    }
   ],
   "source": [
    "print(\"Dimension of this matrix: \",mat1.ndim,sep='') \n",
    "print(\"Size of this matrix: \", mat1.size,sep='') \n",
    "print(\"Shape of this matrix: \", mat1.shape,sep='')\n",
    "print(\"Data type of this matrix: \", mat1.dtype,sep='')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 8: Zeros, Ones, Random, and Identity Matrices and Vectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vector of zeros:  [0. 0. 0. 0. 0.]\n",
      "Matrix of zeros:  [[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n",
      "Vector of ones:  [1. 1. 1. 1.]\n",
      "Matrix of ones:  [[1. 1.]\n",
      " [1. 1.]\n",
      " [1. 1.]\n",
      " [1. 1.]]\n",
      "Matrix of 5’s:  [[5. 5. 5.]\n",
      " [5. 5. 5.]\n",
      " [5. 5. 5.]]\n",
      "Identity matrix of dimension 2: [[1. 0.]\n",
      " [0. 1.]]\n",
      "Identity matrix of dimension 4: [[1. 0. 0. 0.]\n",
      " [0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]\n",
      " [0. 0. 0. 1.]]\n",
      "Random matrix of shape (4,3):\n",
      " [[2 6 1]\n",
      " [9 1 1]\n",
      " [8 7 2]\n",
      " [7 6 9]]\n"
     ]
    }
   ],
   "source": [
    "print(\"Vector of zeros: \",np.zeros(5))\n",
    "print(\"Matrix of zeros: \",np.zeros((3,4)))\n",
    "print(\"Vector of ones: \",np.ones(4))\n",
    "print(\"Matrix of ones: \",np.ones((4,2)))\n",
    "print(\"Matrix of 5’s: \",5*np.ones((3,3)))\n",
    "print(\"Identity matrix of dimension 2:\",np.eye(2))\n",
    "print(\"Identity matrix of dimension 4:\",np.eye(4))\n",
    "print(\"Random matrix of shape (4,3):\\n\",np.random.randint(low=1,high=10,size=(4,3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 9: Reshaping, Ravel, Min, Max, Sorting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of a: (30,)\n",
      "Shape of b: (2, 3, 5)\n",
      "Shape of c: (6, 5)\n"
     ]
    }
   ],
   "source": [
    "a = np.random.randint(1,100,30)\n",
    "b = a.reshape(2,3,5)\n",
    "c = a.reshape(6,5)\n",
    "print (\"Shape of a:\", a.shape)\n",
    "print (\"Shape of b:\", b.shape)\n",
    "print (\"Shape of c:\", c.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "a looks like\n",
      " [ 3 94 42 63 68 39 68 65 61 31 74 19 94  6 96 15  8 15 56 21 95 66 96 60\n",
      "  3 41 31 73 78 52]\n",
      "\n",
      "b looks like\n",
      " [[[ 3 94 42 63 68]\n",
      "  [39 68 65 61 31]\n",
      "  [74 19 94  6 96]]\n",
      "\n",
      " [[15  8 15 56 21]\n",
      "  [95 66 96 60  3]\n",
      "  [41 31 73 78 52]]]\n",
      "\n",
      "c looks like\n",
      " [[ 3 94 42 63 68]\n",
      " [39 68 65 61 31]\n",
      " [74 19 94  6 96]\n",
      " [15  8 15 56 21]\n",
      " [95 66 96 60  3]\n",
      " [41 31 73 78 52]]\n"
     ]
    }
   ],
   "source": [
    "print(\"\\na looks like\\n\",a)\n",
    "print(\"\\nb looks like\\n\",b)\n",
    "print(\"\\nc looks like\\n\",c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 3 94 42 63 68 39 68 65 61 31 74 19 94  6 96 15  8 15 56 21 95 66 96 60\n",
      "  3 41 31 73 78 52]\n"
     ]
    }
   ],
   "source": [
    "b_flat = b.ravel()\n",
    "print(b_flat)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 10: Indexing and slicing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Array: [ 0  1  2  3  4  5  6  7  8  9 10]\n",
      "Element at 7th index is: 7\n",
      "Elements from 3rd to 5th index are: [3 4 5]\n",
      "Elements up to 4th index are: [0 1 2 3]\n",
      "Elements from last backwards are: [10  9  8  7  6  5  4  3  2  1  0]\n",
      "3 Elements from last backwards are: [10  8  6]\n",
      "New array: [ 0  2  4  6  8 10 12 14 16 18 20]\n",
      "Elements at 2nd, 4th, and 9th index are: [ 4  8 18]\n"
     ]
    }
   ],
   "source": [
    "arr = np.arange(0,11)\n",
    "print(\"Array:\",arr)\n",
    "print(\"Element at 7th index is:\", arr[7])\n",
    "print(\"Elements from 3rd to 5th index are:\", arr[3:6])\n",
    "print(\"Elements up to 4th index are:\", arr[:4])\n",
    "print(\"Elements from last backwards are:\", arr[-1::-1])\n",
    "print(\"3 Elements from last backwards are:\", arr[-1:-6:-2])\n",
    "\n",
    "arr2 = np.arange(0,21,2)\n",
    "print(\"New array:\",arr2)\n",
    "print(\"Elements at 2nd, 4th, and 9th index are:\", arr2[[2,4,9]]) # Pass a list as a index to subset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrix of random 2-digit numbers\n",
      " [[89 12 21 92 74]\n",
      " [91 94 56 89 93]\n",
      " [39 49 58 92 63]]\n",
      "\n",
      "Double bracket indexing\n",
      "\n",
      "Element in row index 1 and column index 2: 56\n",
      "\n",
      "Single bracket with comma indexing\n",
      "\n",
      "Element in row index 1 and column index 2: 56\n",
      "\n",
      "Row or column extract\n",
      "\n",
      "Entire row at index 2: [39 49 58 92 63]\n",
      "Entire column at index 3: [92 89 92]\n",
      "\n",
      "Subsetting sub-matrices\n",
      "\n",
      "Matrix with row indices 1 and 2 and column indices 3 and 4\n",
      " [[89 93]\n",
      " [92 63]]\n",
      "Matrix with row indices 0 and 1 and column indices 1 and 3\n",
      " [[12 92]\n",
      " [94 89]]\n"
     ]
    }
   ],
   "source": [
    "mat = np.random.randint(10,100,15).reshape(3,5)\n",
    "print(\"Matrix of random 2-digit numbers\\n\",mat)\n",
    "\n",
    "print(\"\\nDouble bracket indexing\\n\")\n",
    "print(\"Element in row index 1 and column index 2:\", mat[1][2])\n",
    "\n",
    "print(\"\\nSingle bracket with comma indexing\\n\")\n",
    "print(\"Element in row index 1 and column index 2:\", mat[1,2])\n",
    "print(\"\\nRow or column extract\\n\")\n",
    "\n",
    "print(\"Entire row at index 2:\", mat[2])\n",
    "print(\"Entire column at index 3:\", mat[:,3])\n",
    "\n",
    "print(\"\\nSubsetting sub-matrices\\n\")\n",
    "print(\"Matrix with row indices 1 and 2 and column indices 3 and 4\\n\", mat[1:3,3:5])\n",
    "print(\"Matrix with row indices 0 and 1 and column indices 1 and 3\\n\", mat[0:2,[1,3]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 11: Conditional subsetting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrix of random 2-digit numbers\n",
      " [[21 16 77 31 81]\n",
      " [21 50 62 67 14]\n",
      " [33 94 52 39 18]]\n",
      "\n",
      "Elements greater than 50\n",
      " [77 81 62 67 94 52]\n"
     ]
    }
   ],
   "source": [
    "mat = np.random.randint(10,100,15).reshape(3,5)\n",
    "print(\"Matrix of random 2-digit numbers\\n\",mat)\n",
    "print (\"\\nElements greater than 50\\n\", mat[mat>50])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 12: Array operations (array-array, array-scalar, universal functions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "1st Matrix of random single-digit numbers\n",
      " [[1 6 5]\n",
      " [6 2 2]\n",
      " [5 3 5]]\n",
      "\n",
      "2nd Matrix of random single-digit numbers\n",
      " [[9 7 5]\n",
      " [3 9 8]\n",
      " [8 8 9]]\n",
      "\n",
      "Addition\n",
      " [[10 13 10]\n",
      " [ 9 11 10]\n",
      " [13 11 14]]\n",
      "\n",
      "Multiplication\n",
      " [[ 9 42 25]\n",
      " [18 18 16]\n",
      " [40 24 45]]\n",
      "\n",
      "Division\n",
      " [[0.11111111 0.85714286 1.        ]\n",
      " [2.         0.22222222 0.25      ]\n",
      " [0.625      0.375      0.55555556]]\n",
      "\n",
      "Lineaer combination: 3*A - 2*B\n",
      " [[-15   4   5]\n",
      " [ 12 -12 -10]\n",
      " [ -1  -7  -3]]\n",
      "\n",
      "Addition of a scalar (100)\n",
      " [[101 106 105]\n",
      " [106 102 102]\n",
      " [105 103 105]]\n",
      "\n",
      "Exponentiation, matrix cubed here\n",
      " [[  1 216 125]\n",
      " [216   8   8]\n",
      " [125  27 125]]\n",
      "\n",
      "Exponentiation, sq-root using pow function\n",
      " [[1.         2.44948974 2.23606798]\n",
      " [2.44948974 1.41421356 1.41421356]\n",
      " [2.23606798 1.73205081 2.23606798]]\n"
     ]
    }
   ],
   "source": [
    "mat1 = np.random.randint(1,10,9).reshape(3,3)\n",
    "mat2 = np.random.randint(1,10,9).reshape(3,3)\n",
    "print(\"\\n1st Matrix of random single-digit numbers\\n\",mat1)\n",
    "print(\"\\n2nd Matrix of random single-digit numbers\\n\",mat2)\n",
    "\n",
    "print(\"\\nAddition\\n\", mat1+mat2)\n",
    "print(\"\\nMultiplication\\n\", mat1*mat2)\n",
    "print(\"\\nDivision\\n\", mat1/mat2)\n",
    "print(\"\\nLineaer combination: 3*A - 2*B\\n\", 3*mat1-2*mat2)\n",
    "\n",
    "print(\"\\nAddition of a scalar (100)\\n\", 100+mat1)\n",
    "\n",
    "print(\"\\nExponentiation, matrix cubed here\\n\", mat1**3)\n",
    "print(\"\\nExponentiation, sq-root using pow function\\n\",pow(mat1,0.5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Stacking arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrix a\n",
      " [[1 2]\n",
      " [3 4]]\n",
      "Matrix b\n",
      " [[5 6]\n",
      " [7 8]]\n",
      "Vertical stacking\n",
      " [[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]]\n",
      "Horizontal stacking\n",
      " [[1 2 5 6]\n",
      " [3 4 7 8]]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[1,2],[3,4]])\n",
    "b = np.array([[5,6],[7,8]])\n",
    "print(\"Matrix a\\n\",a)\n",
    "print(\"Matrix b\\n\",b)\n",
    "print(\"Vertical stacking\\n\",np.vstack((a,b)))\n",
    "print(\"Horizontal stacking\\n\",np.hstack((a,b)))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
